#include "output_thread.h"

static struct output_thread *output_thread_t = NULL;

static pthread_mutex_t msg_mutex;
static pthread_cond_t msg_list_not_empty;

void wake_up_output_thread() 
{
	pthread_cond_signal( &msg_list_not_empty );
}

int send_message( char *msg )
{
	pthread_mutex_lock( &msg_mutex );
	
	if ( enqueue( output_thread_t->queue, msg ) == -1 ) {
		pthread_mutex_unlock( &msg_mutex );		
		return -1; 
	}

	pthread_mutex_unlock( &msg_mutex );
	pthread_cond_signal( &msg_list_not_empty );

	return 0;
}

void * write_to_socket() 
{
	int len = 0, bytes_sent, ret;
	char *msg;
	int sockfd;

	sockfd = output_thread_t->IRC_core_t->socket_t->sockfd;
	
	while ( output_thread_t->is_running ) {

		pthread_mutex_lock( &msg_mutex );
		pthread_cond_wait( &msg_list_not_empty, &msg_mutex );

		while ( !queue_empty( output_thread_t->queue ) ) {
			
			msg = dequeue( output_thread_t->queue );
			len = strlen( msg );

			bytes_sent = 0;			

			while ( len > bytes_sent ) { 
				ret = send( sockfd, &msg[bytes_sent], len, 0 );
				if ( ret > 0 )
					bytes_sent += ret;
			}
		}
		pthread_mutex_unlock( &msg_mutex );

	}

	output_thread_t->is_running = 0;

	pthread_exit( NULL );
}

struct output_thread * new_output_thread( struct IRC_core *IRC_core_t )
{
	int res;

	output_thread_t = (struct output_thread*) malloc( sizeof( struct output_thread ) );
	if ( output_thread_t == NULL ) {
		fprintf( stderr, "Ouput thread allocation failed, out of memory. \n" );
		return NULL;	
	}
	output_thread_t->IRC_core_t = IRC_core_t;
	
	output_thread_t->queue = new_queue();
	if ( output_thread_t->queue == NULL ) {
		fprintf( stderr, "Failed to create queue.\n" );
		return NULL;
	}

	pthread_mutex_init( &msg_mutex, NULL );
  pthread_cond_init ( &msg_list_not_empty, NULL );

	if ( ( res = pthread_create( &output_thread_t->thread, NULL, write_to_socket, NULL) ) ) {
		fprintf(stderr, "Input thread creation failed: %d\n", res);
		return NULL;
	}

	output_thread_t->is_running = 1;

	return output_thread_t;
}

void delete_output_thread() 
{
	if ( output_thread_t ) {
		delete_queue( output_thread_t->queue );
		free( output_thread_t ); 
	}	
	pthread_mutex_destroy( &msg_mutex );
  pthread_cond_destroy ( &msg_list_not_empty );
}
